package com.example.springsecuritydemo.filter;

import com.example.springsecuritydemo.entities.SecurityUser;
import com.example.springsecuritydemo.security.TokenManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;

/**
 * Created with IntelliJ IDEA.
 * Description:
 *
 * @author lzy
 * @date 2021-06-25 下午3:40
 */
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
    private final TokenManager tokenManager;

    public TokenAuthenticationFilter(AuthenticationManager authenticationManager, TokenManager tokenManager) {
        super(authenticationManager);
        this.tokenManager = tokenManager;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        final Optional<UsernamePasswordAuthenticationToken> authentication = getAuthentication(request);
        final Boolean flag = authentication.map(auth -> {
            SecurityContextHolder.getContext().setAuthentication(auth);
            return true;
        }).orElseGet(() -> {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        });

        if (flag) {
            chain.doFilter(request, response);
        }
    }

    private Optional<UsernamePasswordAuthenticationToken> getAuthentication(HttpServletRequest request) {
        final String token = request.getHeader("Authorization");
        if (StringUtils.isNotBlank(token)) {
            final Optional<SecurityUser> securityUser = tokenManager.getUserByToken(token);
            return securityUser.map(user -> new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities()));
        }

        return Optional.empty();
    }
}
